package net.pws.oos.biz.service.storage;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.swing.JLabel;

import net.pws.common.util.DateUtils;
import net.pws.common.util.ImageUtils;
import net.pws.common.util.IoUtil;
import net.pws.common.util.StringUtils;
import net.pws.oos.biz.model.Attachment;
import net.pws.oos.biz.model.Locatable;
import net.pws.oos.biz.model.PhotoMarker;

import org.springframework.web.multipart.MultipartFile;

public class PhotoMarkerStorage implements FileStorage {
    
    public static final String DEFAULT_EXT_NAME = ".jpg";
    
    private static final String FONT = "宋体";
    
    private static Map<Integer, Integer> fontSizeMap = new HashMap<Integer, Integer>();
    
    private String[] validExtensions = { "jpg", "png", "gif" };
    
    private MultipartFile content;
    
    private String orginalPath; // 原始图片的路径
    
    private String largePath;
    
    private String mediumPath;
    
    private String smallPath;
    
    private List<PhotoMarker> markers;
    
    private Locatable locatable;
    
    private Attachment attachment;
    
    public PhotoMarkerStorage(MultipartFile content,
                              String orginalPath,
                              String largePath,
                              String mediumPath,
                              String smallPath,
                              List<PhotoMarker> markers,
                              Attachment attachment,
                              Locatable locatable) {
        this.content = content;
        this.orginalPath = orginalPath;
        this.largePath = largePath;
        this.mediumPath = mediumPath;
        this.smallPath = smallPath;
        this.markers = markers;
        this.attachment = attachment;
        this.locatable = locatable;
    }
    
    public String[] getValidExtensions() {
        return validExtensions;
    }
    
    public void store() throws Exception {
        // 检查路径
        String sourceFolder = IoUtil.getFolder(orginalPath);
        new File(sourceFolder).mkdirs();
        
        // 保存源图片
        // File orginPhoto = new File(orginalPath);
        content.transferTo(new File(orginalPath));
        
        // 保存添加标记的大图
        String[] texts = createMarkText();
        createMarkers(orginalPath, largePath, markers, texts);
        File largePhoto = new File(largePath);
        
        // 创建中等缩略图
        ImageUtils.createSnapshot(largePhoto, mediumPath, 600, 400, true);
        
        // 创建小型缩略图
        ImageUtils.createSnapshot(largePhoto, smallPath, 300, 200, true);
    }
    
    private String[] createMarkText() {
        String[] texts = new String[2];
        if (locatable.getLongitude() == null || locatable.getLatitude() == null) {
            texts[0] = "未定位";
        }
        else {
            StringBuilder sb = new StringBuilder("经度:");
            sb.append(formatBigDecimal(locatable.getLongitude()));
            sb.append(" 纬度:");
            sb.append(formatBigDecimal(locatable.getLatitude()));
            texts[0] = sb.toString();
        }
        texts[texts.length - 1] = "时间:" + DateUtils.getDateTimeStr(attachment.getCreateDate());
        return texts;
    }
    
    private String formatBigDecimal(BigDecimal bd) {
        if (bd == null) {
            return null;
        }
        NumberFormat format = new DecimalFormat("#.#######");
        return format.format(bd);
    }
    
    public static void createMarkers(String orginPath,
                                     String markerPath,
                                     List<PhotoMarker> markers) throws Exception {
        createMarkers(orginPath, markerPath, markers, null);
    }
    
    public static void createMarkers(String orginPath,
                                     String markerPath,
                                     List<PhotoMarker> markers,
                                     String[] texts) throws Exception {
        File orginFile = new File(orginPath);
        File markerFile = new File(markerPath);
        
        BufferedImage orginImage = ImageIO.read(orginFile);
        Graphics2D g2d = orginImage.createGraphics();
        g2d.setColor(Color.RED);
        
        // 绘制形状标注
        if (markers != null && markers.size() > 0) {
            for (int i = 0; i < markers.size(); i++) {
                PhotoMarker marker = markers.get(i);
                if (PhotoMarker.RECT == marker.getType()) {
                    g2d.drawRect((int) marker.getLeft(),
                                 (int) marker.getTop(),
                                 (int) marker.getWidth(),
                                 (int) marker.getHeight());
                }
                else if (PhotoMarker.OVAL == marker.getType()) {
                    g2d.drawOval((int) marker.getLeft(),
                                 (int) marker.getTop(),
                                 (int) marker.getWidth(),
                                 (int) marker.getHeight());
                }
                drawText(g2d, marker, String.valueOf(i + 1));
            }
        }
        
        // 绘制文字水印
        int maxTextWidth = orginImage.getWidth() / 2;
        int fontSize = getFontSizeByWidth(maxTextWidth, maxString(texts)); // 使用时间计算文字长度
        if (fontSize > 0) {
            int fontHeight = computeFontHeight(fontSize);
            g2d.setFont(new Font(FONT, Font.BOLD, fontSize));
            for (int i = 0; i < texts.length; i++) {
                String text = texts[texts.length - i - 1];
                // 画白色的当阴影
                g2d.setColor(Color.WHITE);
                g2d.drawString(text, 6, orginImage.getHeight() - fontHeight
                                        * i
                                        - 9);
                // 真正的水印
                g2d.setColor(Color.GREEN);
                g2d.drawString(text, 5, orginImage.getHeight() - fontHeight
                                        * i
                                        - 10);
            }
        }
        g2d.dispose();
        
        ImageIO.write(orginImage, "JPEG", markerFile);
    }
    
    private static void drawText(Graphics2D g2d,
                                 PhotoMarker marker,
                                 String index) {
        int fontSize = computeFontSize(marker);
        g2d.setFont(new Font(FONT, Font.PLAIN, fontSize));
        float x = marker.getRight() - fontSize;
        float y = (float) (marker.getTop() + fontSize);
        
        g2d.drawString(index, x, y);
    }
    
    private static int computeFontSize(PhotoMarker marker) {
        if (marker == null) {
            return 10;
        }
        int h = (int) marker.getHeight() / 4;
        int w = (int) marker.getWidth() / 4;
        return h < w ? h : w;
    }
    
    private static int getFontSizeByWidth(Integer width, String marker) {
        if (fontSizeMap.containsKey(width)) {
            return fontSizeMap.get(width);
        }
        
        int fontSize = computeFontSize(width, marker);
        if (fontSize > 0) {
            fontSizeMap.put(width, fontSize);
        }
        
        return fontSize;
    }
    
    private static int computeFontSize(int width, String marker) {
        if (StringUtils.isBlank(marker)) {
            return 0;
        }
        for (int i = 99; i > 2; i--) {
            Font f = new Font(FONT, Font.BOLD, i);
            FontMetrics fm = new JLabel().getFontMetrics(f);
            int fontWidth = fm.stringWidth(marker);
            if (fontWidth < width) {
                return i;
            }
        }
        return 2;
    }
    
    private static int computeFontHeight(int fontSize) {
        Font f = new Font(FONT, Font.BOLD, fontSize);
        FontMetrics fm = new JLabel().getFontMetrics(f);
        return fm.getHeight();
    }
    
    private static String maxString(String[] strings) {
        if (strings == null || strings.length == 0) {
            return null;
        }
        // String max = "";
        // for (String s : strings) {
        // if (s != null && s.length() > max.length()) {
        // max = s;
        // }
        // }
        // return max;
        
        return strings[strings.length - 1];
    }
    
    public static void main(String[] args) throws Exception {
        String orginPath = "/Users/LiangBin/Desktop/1.jpg";
        String markerPath = "/Users/LiangBin/Desktop/2.jpg";
        List<PhotoMarker> list = new ArrayList<PhotoMarker>();
        
        PhotoMarker marker = new PhotoMarker();
        marker.setType(PhotoMarker.RECT);
        marker.setLeft(440);
        marker.setRight(889);
        marker.setTop(320);
        marker.setBottom(643);
        list.add(marker);
        
        String[] texts = new String[] { "经度:104.152853 维度:30.602817",
                                       "时间:2014-04-21 21:09:43" };
        createMarkers(orginPath, markerPath, list, texts);
    }
}
